#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright (c) 2025 粤港澳大湾区（广东）国创中心

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

File: PythonPreviewDlg.py
Desc: A preview dialog that shows images of modeling operations.
Author: xumanjia
Date: 2025-08-01
"""
import sys
import os

from PyQt5.QtWidgets import QLabel, QGraphicsOpacityEffect
from PyQt5.QtCore import Qt, QPoint, QEvent, QPropertyAnimation, QEasingCurve
from PyQt5.QtGui import QPixmap
 
class PreviewLabel(QLabel):
    MIN_WIDTH = 200
    RESIZE_MARGIN = 10
    ASPECT_RATIO = 1.5      # 宽度 = 高度 * 1.5
    _is_resizing = False    # 标记是否正在调整宽度
    _resize_start_global_x = 0
    _original_width = 0
    _original_geometry = None

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowFlags(
            Qt.FramelessWindowHint |    # 无边框
            Qt.Tool |                   # 设置为工具窗口
            Qt.WindowStaysOnTopHint     # 置顶显示
        )
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setMouseTracking(True)  
        self.setStyleSheet("background: white; border: 1px solid black;")
        self._offset = QPoint(0, 0)  
        self.displayLocation = "left"
        self._parent = parent
        if parent:
            parent_height = parent.frameGeometry().height()
            self.setFixedHeight(parent_height)
            self.setMinimumWidth(self.MIN_WIDTH)
            self.resize(self.MIN_WIDTH, parent_height)

        # 标题 → 图片路径 的映射（可根据需求扩展）
        current_dir = os.path.dirname(os.path.abspath(__file__))
        resource_dir = os.path.join(current_dir, "..", "resource", "Preview")
        self.title_to_image = {
            "创建长方体参数": os.path.join(resource_dir, "create_box.png"),
            "创建圆柱体参数": os.path.join(resource_dir, "create_cylinder.png"),
            "布尔": os.path.join(resource_dir, "boolean.png"),
            "圆角": os.path.join(resource_dir, "fillet.png"),
            "倒角": os.path.join(resource_dir, "chamfer.png"),
            "平移": os.path.join(resource_dir, "pan.png"),
            "缩放": os.path.join(resource_dir, "scale.png"),
            "旋转": os.path.join(resource_dir, "rotate_body.png"),
            "拉伸": os.path.join(resource_dir, "prism.png"),
            "直线阵列": os.path.join(resource_dir, "linear_array.png"),
            "旋转阵列": os.path.join(resource_dir, "rotating_array.png"),
            "查找小特征": os.path.join(resource_dir, "find_small_features.png"),
            "查找圆角": os.path.join(resource_dir, "find_fillets.png"),
            "查找LOGO": os.path.join(resource_dir, "find_logos.png"),
            "查找孔": os.path.join(resource_dir, "find_holes.png"),
            "网格设置": os.path.join(resource_dir, "face_mesh.png"), 
            "请输入网格参数": os.path.join(resource_dir, "volume_mesh.png"),
            "添加集中力参数": os.path.join(resource_dir, "add_force.png"),
            "单点约束": os.path.join(resource_dir, "add_spc.png")
        }

        parent.closePreview.connect(self.close) # 连接弹窗关闭时发出的信号，关闭此窗口

    def update_preview_image(self):
        if not self._parent:
            self.hide()
            return
 
        parent_title = self._parent.windowTitle()
        image_path = self.title_to_image.get(parent_title)
 
        if image_path:
            pixmap = QPixmap(image_path)
            if not pixmap.isNull():
                scaled_pixmap = pixmap.scaledToHeight(
                    self.height() - 10,
                    Qt.SmoothTransformation
                )
                self.setScaledContents(True)  # 启用自动拉伸填充
                self.setPixmap(scaled_pixmap)
                self.show()  # 有图片时显示窗口
            else:
                self.setPixmap(QPixmap())
                self.hide()  # 图片加载失败时隐藏
        else:
            self.setPixmap(QPixmap())
            self.hide()  # 无匹配图片时不显示

    def set_relative_position(self):
        if self.displayLocation == "left":
            self._offset = QPoint(-self.width(), 0)
        elif self.displayLocation == "right":
            self._offset = QPoint(self._parent.width(), 0)
 
    def update_position(self):
        if not self._parent:
            self.hide()
            return
        parent_height = self._parent.frameGeometry().height()
        content_height = self._parent.height()
        title_bar_height = parent_height - content_height

        new_height = parent_height
        new_width = int(new_height * self.ASPECT_RATIO)
        self.setFixedHeight(new_height)
        self.setMinimumWidth(new_width)
 
        # 更新位置
        self.set_relative_position()
        parent_pos = self._parent.mapToGlobal(QPoint(0, 0)) # 获得的是内容区域的坐标，后续Y方向要减去标题栏的高度
        parent_pos = QPoint(parent_pos.x(), parent_pos.y() - title_bar_height)
        self.move(parent_pos + self._offset)
        self.update_preview_image()
 
    def mousePressEvent(self, event):
        # 为左侧界面的时候，左侧边框可拖动改变大小，右侧界面则为右侧可动
        if event.button() == Qt.LeftButton:
            self._is_resizing = True
            if self.displayLocation == "left":
                if abs(event.pos().x()) < self.RESIZE_MARGIN:
                    self._resize_start_global_x = event.globalX()
                    self._original_geometry = self.geometry()  # 记录完整几何信息
                    self.setCursor(Qt.SizeHorCursor)
            elif self.displayLocation == "right":
                if abs(event.pos().x() - self.width()) < self.RESIZE_MARGIN:
                    self._resize_start_global_x = event.globalX()
                    self._original_width = self.width()
                    self.setCursor(Qt.SizeHorCursor)
        else:
            super().mousePressEvent(event)
                
    def mouseMoveEvent(self, event):
        if self._is_resizing:
            delta_x = event.globalX() - self._resize_start_global_x
            if self.displayLocation == "left" and self._original_geometry:
                new_x = self._original_geometry.x() + delta_x
                new_width = self._original_geometry.width() - delta_x
                if new_width >= self.minimumWidth():
                    self.setGeometry(new_x, self.y(), new_width, self.height())
            elif self.displayLocation == "right":
                new_width = self._original_width + delta_x
                self.resize(max(new_width, self.minimumWidth()), self.height())
        else:
            self.updateResizeCursor(event.pos())
            super().mouseMoveEvent(event)

 
    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton and self._is_resizing:
            self._is_resizing = False
            self.unsetCursor()  # 恢复光标
        else:
            super().mouseReleaseEvent(event)

    def updateResizeCursor(self, pos):
        if self.displayLocation == "left" and abs(pos.x()) < self.RESIZE_MARGIN:
            self.setCursor(Qt.SizeHorCursor)
        elif self.displayLocation == "right" and abs(pos.x() - self.width()) < self.RESIZE_MARGIN:
            self.setCursor(Qt.SizeHorCursor)
        else:
            self.unsetCursor()
 
    def showEvent(self, event):
        self.update_position()
        super().showEvent(event)
 
    def eventFilter(self, obj, event):
        """监听父窗口事件（移动/调整大小）"""
        if obj == self._parent:
            if event.type() in (QEvent.Move, QEvent.Resize):
                self.update_position()
        return super().eventFilter(obj, event)
    
    def close(self):
        if self._parent:
            self._parent.removeEventFilter(self)
        self.hide()
        self.deleteLater()  # 确保对象被删除
